/**
 * main.cpp
 * This file is part of the YATE Project http://YATE.null.ro
 *
 * Yet Another Telephony Engine - a fully featured software PBX and IVR
 * Copyright (C) 2004-2014 Null Team
 *
 * This software is distributed under multiple licenses;
 * see the COPYING file in the main directory for licensing
 * information for this specific distribution.
 *
 * This use of this software may be subject to additional restrictions.
 * See the LEGAL file in the main directory for details.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "Aux_cmd_define.h"
#include "Aux_yate_hal.h"


using namespace TelEngine;

static int s_argc;
static const char** s_argv;

#ifdef _WITH_YATE_QT_

#include <QApplication>
#include <QtCore>
#include <QThread>
#include <QDebug>

#include "libgitlevtbus/gitlmodule.h"
#include "libgitlevtbus/gitleventbus.h"

#include "YateQtWrapper.h"

static QCoreApplication* s_app;



class MainPlugin : public Module
{
public:
	MainPlugin(int pro = 100) :
		Module("QtMainPlugin")
	{
		m_initialized = false;
	}

	~MainPlugin() {
	}

	enum Relay {
		// Stop = Private,
		Start = Private << 1,
		Init = Private << 2,
	};

	virtual void initialize(void);
	virtual bool received(Message& msg, int id);

public:

	void onEngineStart();
	void onEngineStop();

	bool onYateMessage(Message& msg);

	bool onQtAppMsg(Message& msg);

	bool m_bStop;

private:

	bool m_initialized;


};

static MainPlugin sViewPlugin;


void MainPlugin::initialize()
{
	Output("Initializing module qt-main-plugin");

	if (!m_initialized) {

		m_initialized = true;

		installRelay(Stop);
		installRelay(Start, "engine.start");
		//installRelay(Init, "engine.init");

		YateMsgHandler* handler;

		handler = new YateMsgHandler(MSG_YATE);
		handler->_handler = [this](Message& msg) {
			return this->onYateMessage(msg);
			};
		Engine::install(handler);

		handler = new YateMsgHandler("qt.app");
		handler->_handler = [this](Message& msg) {
			return this->onQtAppMsg(msg);
			};
		Engine::install(handler);


	}


}

bool MainPlugin::received(Message& msg, int id)
{

	if (id == Halt) {
		//Debug(this, DebugInfo, "MainPlugin::received - Halt");
	}
	else if (Start == id) {
		onEngineStart();
		return false;
	}
	else if (Stop == id) {
		onEngineStop();
		return false;
	}
	return false;
}

void MainPlugin::onEngineStop()
{


}

void MainPlugin::onEngineStart()
{
	Message* msg = new Message("qt.cmd", 0, true);
	msg->setParam("Op", "app.start");

	std::shared_ptr<YateQtWrapper> w = std::make_shared<YateQtWrapper>();

	w->_app = s_app;

	w->_event_bus = GitlEventBus::getInstance();

	AnyRefObject<YateQtWrapper>* user_data = new AnyRefObject<YateQtWrapper>();

	user_data->set(w);

	msg->userData(user_data);

	TE::Engine::enqueue(msg);

	// 释放本地引用，由msg消息持有引用
	user_data->deref();

}

bool MainPlugin::onYateMessage(Message& msg)
{
	String op = msg.getParam("Op");



	return false;
}


bool MainPlugin::onQtAppMsg(Message& msg)
{
	String op = msg.getParam("Op");

	AnyRefObject<QCoreApplication>* user_data = new AnyRefObject<QCoreApplication>();

	user_data->set(s_app);

	msg.userData(user_data);

	QCoreApplication* app = AnyRefObject_np<QCoreApplication>(msg);

	// 释放本地引用，由msg消息持有引用
	user_data->deref();

	msg.retValue() = "ok";

	return true;
}

/*
* 支持模块内日志宏
*/

TelEngine::DebugEnabler* withDebugEnabler()
{
	return &sViewPlugin;
}



int my_engine_loop()
{

    int ret =  0;

    YateThread* t = new YateThread("Engine Loop");

    t->_fun = [&]() {
        ret = TE::Engine::self()->run();
        };

    t->_clean = [&]() {
        t = nullptr;
        QCoreApplication::quit();
        };

    t->startup();

    s_app->exec();

    return ret;
}


#else

int my_engine_loop()
{
    int ret = 0;
    ret = TE::Engine::self()->run(); 
    return ret;
}


#endif


extern "C" 
int main(int argc, const char** argv, const char** envp)
{
    s_argc = argc;  s_argv = argv;

#ifdef _WITH_YATE_QT_

	s_app = new QCoreApplication(s_argc, (char**)s_argv);

	/*
	GitlModule cModule;

	/// subscribe to an event
	cModule.subscribeToEvtByName("I am a test event",
		[](GitlEvent& rcEvt)->bool
		{
			Q_UNUSED(rcEvt)
			S_INFO( "Hello GitlEvtBus!, #######################################" );
			return true;
		}
	);
	*/

#endif


#ifdef _WIN32
    TelEngine::debugLevel(TelEngine::DebugInfo);
#endif

    return TelEngine::Engine::main(argc,argv,envp,TE::Engine::Console,my_engine_loop);
}
